﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Jayden.Dll.Web.Controls;
using Jayden.Dll.Web;
using Jayden.Dll.Sc2;
using Jayden.Dll.Sc2.Descriptions;
using Jayden.Dll.Web.HtmlControls;
using Jayden.Dll.Web.Events;
using Jayden.Sc2;

namespace Jayden.Site.Sc2.Dll
{
	public class BuildOrderForm : Form
	{
		public delegate void OnActionExecuted(HttpHandlerContext context, ActionDescription action, GameState state);
		public delegate void OnActionFailed(HttpHandlerContext context, ActionDescription action, GameState state);

		public class ExecuteActionCommandHandler : HttpCommandHandler
		{
			public ExecuteActionCommandHandler() : this("ExecuteAction") { }
			public ExecuteActionCommandHandler(string command)
				: base(command)
			{
				RegisterEvent("ActionExecuted");
				RegisterEvent("ActionFailed");
			}
			public event OnActionExecuted ActionExecuted { add { AddEvent<OnActionExecuted>("ActionExecuted", value); } remove { RemoveEvent<OnActionExecuted>("ActionExecuted", value); } }
			public event OnActionFailed ActionFailed { add { AddEvent<OnActionFailed>("ActionFailed", value); } remove { RemoveEvent<OnActionFailed>("ActionFailed", value); } }

			protected override void ProcessCommand(HttpHandlerContext context, string command)
			{
				string actionId = context.Context.Request["actionId"];

				ActionDescription action = null;
				GameState gameState = null;

				action = RaceDictionary.Instance.GetAction(actionId);
				if(action != null)
				{
					gameState = context.Context.Session["GameState"] as GameState;
					if (gameState == null || gameState.Race.Id != action.Entity.Race.Id)
						gameState = new GameState(action.Entity.Race);

					if (gameState != null)
					{
						if (gameState.Execute(action))
						{
							context.Context.Session["GameState"] = gameState;
							context.Context.Session["ActionList"] = new ActionList(gameState.ActionList);
							Invoke("ActionExecuted", context, action, gameState);
						}
						else
						{
							ActionList actionList = new ActionList(gameState.ActionList);
							gameState.Reset();
							gameState.Execute(actionList);
							Invoke("ActionFailed", context, action, gameState);
						}
					}
				}
			}
		}

		private Select m_ActionId;
		private Input m_Execute;
		private Table m_ActionList;

		public Sc2PageHtml Page { get { return Root as Sc2PageHtml; } }

		public override void Load(System.Xml.XmlNode node, HtmlControlLoader loader)
		{
			base.Load(node, loader);

			m_ActionId = GetElementByServerId<Select>("actionId", true, true);
			m_Execute = GetElementByServerId<Input>("execute", true, false);
			m_ActionList = GetElementByServerId<Table>("actionList", true);
		}

		public override void ProcessHtmlRequest(HttpHandlerContext context)
		{
			FillFromContext(context);
			base.ProcessHtmlRequest(context);
			ExecuteActionCommandHandler executeAction = context.HandlerManager.GetHandler<ExecuteActionCommandHandler>();
			executeAction.ActionExecuted += new OnActionExecuted(ActionExecuted);
		}

		private void ActionExecuted(HttpHandlerContext context, ActionDescription a, GameState state)
		{
			FillFromContext(context);
			m_ActionId.SelectedValue = a.Id;
		}

		private GameState GetGameState(RaceDescription race, HttpHandlerContext context)
		{
			GameState state = context.Context.Session["GameState"] as GameState;
			if (state == null || state.Race.Id != race.Id)
			{
				state = new GameState(race);
				ActionList actionList = GetActionList(race, context);
				state.Execute(actionList);
			}
			return state;
		}

		private ActionList GetActionList(RaceDescription race, HttpHandlerContext context)
		{
			ActionList actionList = context.Context.Session["ActionList"] as ActionList;
			if (actionList == null)
				actionList = new ActionList();
			return actionList;
		}

		protected void FillFromContext(HttpHandlerContext context)
		{
			m_ActionId.Clear();
			m_ActionList.Clear();
			RaceDescription race = Page.Race;
			if (race != null)
			{
				GameState state = GetGameState(race, context);
				m_ActionId.AddDefaultOption();
				foreach (ActionDescription action in state.Actions)
					m_ActionId.AddOption(action.Id, action.Name);

				int index = 0;
				GameState info = new GameState(race);
				THead thead = m_ActionList.AddTHead();
				TBody tbody = m_ActionList.AddTBody();
				Tr tr = thead.AddTr();
				tr.AddTh("#", null, "Time", "Action", "Mineral", "Vespene", "Food");
				foreach (ActionDescription action in state.ActionList)
				{
					tr = tbody.AddTr();
					tr.SetDataAttribute("action-index", index.ToString());
					tr.SetDataAttribute("action-id", action.Id);
					info.Execute(action);
					index++;
					Td[] tds = tr.AddTd
					(
						index.ToString(),
						null,
						info.TimeString,
						action.Name,
						((int)(info.Mineral)).ToString(),
						((int)(info.Vespene)).ToString(),
						info.FoodUsed + "/(" + (info.Food + info.FoodUsed) + "+" + info.FoodBuilding + ")"
					);
					tds[1].AddImg(action.IconId, "/Images/" + action.IconId + ".gif");
				}
			}
		}
	}
}
